<?php
declare(strict_types=1);
/**
 * 执行操作with重试机制
 */
class execWithRetry
{
    private $judgeRetry;

    private $mainFunc;

    //判断是否成功
    public function setJudgeRetry(callable $func)
    {
        $this->judgeRetry = $func;
        return $this;
    }

    //Call the foobar() function with 2 arguments ["foobar", array("one", "two")]
    //Call the $foo->bar() method with 2 arguments [array($foo, "bar"), array("three", "four")]
    public function setMainFunc(callable $func, $args)
    {
        $this->mainFunc = [$func, $args];
        return $this;
    }

    /**
     * @param int $maxRetries 最大尝试次数
     * @return mixed|null
     */
    public function boot(int $maxRetries)
    {
        $retryCount = 0;
        $retry = true;
        $finalResult = null;
        while ($retryCount < $maxRetries && $retry) {
            $res = call_user_func_array(...$this->mainFunc);//需要执行的操作
            $retry = call_user_func($this->judgeRetry, $res);//判断操作是否需要重试

            $finalResult = $res;
            $retryCount++;
//            sleep(1);
        }
        return $finalResult;
    }
}

class myWork
{
    public function main($a)
    {
        $res = ['status' => '', 'error' => ''];
        $k = rand(1, 10);
        echo ('the random number of function main is :' . $k . PHP_EOL);
        if (($a + $k) < 5) {
            $res['status'] = 'pending';
        } elseif (8 == ($a + $k)) {
            $res['status'] = 'success';
        } else {
            $res['status'] = 'error';
        }
        return $res;
    }
}

$myWork = new myWork();

$retry = new execWithRetry();
$finalRes = $retry->setMainFunc([$myWork, 'main'], [0])->setJudgeRetry(function ($res) {
    return isset($res['status']) && 'pending' == $res['status'];
})->boot(3);

var_export($finalRes);

